package com.sjtu.service;

import com.sjtu.constants.ApiConstants;
import com.sjtu.constants.TaskConstants;
import com.sjtu.dao.model.JobRunHistory;
import com.sjtu.dao.model.TaskInfo;
import com.sjtu.dao.repository.JobRunHistoryRepository;
import com.sjtu.dao.repository.TaskInfoRepository;
import com.sjtu.form.JobInvokeForm;
import com.sjtu.zookeeper.InstanceDetails;
import com.sjtu.zookeeper.ServiceDiscoverUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.x.discovery.ServiceInstance;
import org.apache.curator.x.discovery.ServiceProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.context.ApplicationContext;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

/**
 * nerine
 * 3/2/2020
 */
@Slf4j
@Service
public class JobRerunService {
    @Autowired
    private TaskInfoRepository taskInfoRepository;
    @Autowired
    private DiscoveryClient discoveryClient;
    @Autowired
    private WebClient webClient;
    @Autowired
    private ApplicationContext context;
    @Autowired
    private CuratorFramework curatorFramework;
    @Autowired
    private JobRunHistoryRepository jobRunHistoryRepository;

    public void rerun(JobRunHistory runHistory) {
        if(runHistory.getStatus() != TaskConstants.TaskRunStatus.FAIL) {
            log.info("task status is not fail, do not rerun");
            return;
        }
        TaskInfo taskInfo = runHistory.getTaskInfo();

        ServiceProvider<InstanceDetails> provider =
                ServiceDiscoverUtil.getServiceProvider(taskInfo.getClientInfo().getSystemId());

        JobInvokeForm form = new JobInvokeForm(runHistory.getIdJobRunHistory(),
                taskInfo.getClientInfo().getSystemId(),
                taskInfo.getBeanName());
        Mono<JobInvokeForm> mono = Mono.just(form);

        try {
            short result = webClient.post()
                    .uri(concatHttpUrl(provider.getInstance()))
                    .contentType(MediaType.APPLICATION_JSON)
                    .body(mono, JobInvokeForm.class)
                    .retrieve()
                    .bodyToMono(Short.class)
                    .block().shortValue();
            if(result == ApiConstants.SUCCESS) {
                runHistory.setStatus(TaskConstants.TaskRunStatus.RUNNING);
            }else if(result == ApiConstants.FAIL || result == ApiConstants.NO_SERVICE_FOUND) {
                runHistory.setStatus(TaskConstants.TaskRunStatus.FAIL);
                runHistory.setRemark("client return code: " + result);
            }
        }catch (Exception e) {
            log.error("error in task send:", e);
            runHistory.setStatus(TaskConstants.TaskRunStatus.FAIL);
            runHistory.setRemark(ExceptionUtils.getRootCauseMessage(e));
        }
        jobRunHistoryRepository.save(runHistory);
    }

    String concatHttpUrl(ServiceInstance<InstanceDetails> serviceInstance) {
        return "http://" + serviceInstance.getAddress() + ":" + serviceInstance.getPort() + ApiConstants.CLIENT_INVOKE_URL;
    }
}
